package com.qxbb.report.utils;






import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期时间工具类
 * 采用 JAVA 8 新特性 LocalDate LocalDateTime LocalTime Instant 进行实现
 *
 * @author Z0001
 * @since 2020-03-17
 */
public class DateTimeUtil {

    private static final String DATE_REG = "\\d{4}+[-]\\d{1,2}+[-]\\d{1,2}+";

    /**
     * 获取网络时间
     *
     * @param timeFormatter 格式化规则
     * @return 时间字符串
     */
    public static String getInternetTime(TimeFormatter timeFormatter) {
        return DateTimeUtil.getNowTime(timeFormatter);
    }

    /**
     * 获取当前时间 本地时间
     *
     * @param timeFormatter 格式化规则
     * @return 时间字符串
     */
    public static String getNowTime(TimeFormatter timeFormatter) {
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormatter.getCode(), Locale.CHINA);
        return formatter.format(localDateTime);
    }

    /**
     * 获取当前时间 本地时间 延后多久
     *
     * @param timeFormatter 输出格式化规则
     * @param timeUnit      添加的时间单位
     * @param addValue      延后值
     * @return 时间字符串
     */
    public static String getNowTimePlus(int addValue, TimeFormatter timeFormatter, TimeUnit timeUnit) {
        LocalDateTime localDateTime = LocalDateTime.now();

        switch (timeUnit) {
            case DAYS:
                localDateTime = localDateTime.plusDays(addValue);
                break;
            case HOURS:
                localDateTime = localDateTime.plusHours(addValue);
                break;
            case MINUTES:
                localDateTime = localDateTime.plusMinutes(addValue);
                break;
            case SECONDS:
                localDateTime = localDateTime.plusSeconds(addValue);
                break;
            default:
                break;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormatter.getCode(), Locale.CHINA);
        return localDateTime.format(formatter);
    }

    /**
     * 返回时间差
     *
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param timeFormatter 格式化方式
     * @return 时间差 seconds
     */
    public static long getTimeDiff(String startTime, String endTime, TimeFormatter timeFormatter) {
        if(StringUtils.isEmpty(startTime)|| StringUtils.isEmpty(endTime)){
            return 0;
        }
        return DateTimeUtil.getTimeDiff(startTime, endTime, TimeUnit.SECONDS, timeFormatter);
    }

    /**
     * 返回时间差
     *
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param timeUnit      返回时间类型 default mill seconds
     * @param timeFormatter 格式化方式
     * @return 时间差
     */
    public static long getTimeDiff(String startTime, String endTime, TimeUnit timeUnit, TimeFormatter timeFormatter) {
        LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern(timeFormatter.getCode()));
        LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern(timeFormatter.getCode()));
        return DateTimeUtil.getTimeDiff(start, end, timeUnit);
    }

    /**
     * 返回时间差
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 时间差 seconds
     */
    public static long getTimeDiff(LocalDateTime startTime, LocalDateTime endTime) {
        return DateTimeUtil.getTimeDiff(startTime, endTime, TimeUnit.SECONDS);
    }

    /**
     * 返回时间差
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeUnit  返回时间类型 default mill seconds
     * @return 时间差
     */
    public static long getTimeDiff(LocalDateTime startTime, LocalDateTime endTime, TimeUnit timeUnit) {
        //计算时间差
        Duration duration = Duration.between(startTime, endTime);

        if (timeUnit == null || timeUnit == TimeUnit.MILLISECONDS) {
            return duration.toMillis();
        }

        switch (timeUnit) {
            case DAYS:
                return duration.toDays();
            case HOURS:
                return duration.toHours();
            case MINUTES:
                return duration.toMinutes();
            case SECONDS:
                return duration.toMillis();
            default:
                return 0L;
        }
    }

    /**
     * 将时间字符串转换为时间戳
     *
     * @param time          时间字符串
     * @param timeFormatter 格式化方式
     * @return 时间戳Long值
     */
    public static Long DateTimeToTimestamp(String time, TimeFormatter timeFormatter) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormatter.getCode(), Locale.CHINA);
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
        return localDateTime.toEpochSecond(ZoneOffset.of("+8"));
    }


    /**
     * 将毫秒转换为年月日时分秒
     *
     * @author GaoHuanjie
     */
    public static String getYearMonthDayHourMinuteSecond(long timeMillis) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
        calendar.setTimeInMillis(timeMillis);
        int year = calendar.get(Calendar.YEAR);

        int month = calendar.get(Calendar.MONTH) + 1;
        String mToMonth = null;
        if (String.valueOf(month).length() == 1) {
            mToMonth = "0" + month;
        } else {
            mToMonth = String.valueOf(month);
        }

        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String dToDay = null;
        if (String.valueOf(day).length() == 1) {
            dToDay = "0" + day;
        } else {
            dToDay = String.valueOf(day);
        }

        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        String hToHour = null;
        if (String.valueOf(hour).length() == 1) {
            hToHour = "0" + hour;
        } else {
            hToHour = String.valueOf(hour);
        }

        int minute = calendar.get(Calendar.MINUTE);
        String mToMinute = null;
        if (String.valueOf(minute).length() == 1) {
            mToMinute = "0" + minute;
        } else {
            mToMinute = String.valueOf(minute);
        }

        int second = calendar.get(Calendar.SECOND);
        String sToSecond = null;
        if (String.valueOf(second).length() == 1) {
            sToSecond = "0" + second;
        } else {
            sToSecond = String.valueOf(second);
        }
        return year + "-" + mToMonth + "-" + dToDay + " " + hToHour + ":" + mToMinute + ":" + sToSecond;
    }

    /**
     * 获取当前网络时间
     *
     * @return
     */
    public static LocalDateTime getNowTime() {
        return LocalDateTime.parse(DateTimeUtil.getInternetTime(TimeFormatter.YYYY_MM_DD_HH_MM_SS), DateTimeFormatter.ofPattern(TimeFormatter.YYYY_MM_DD_HH_MM_SS.getCode(),
                Locale.CHINA));
    }

    /**
     * 更新时间月str
     *
     * @param endTime  结束时间
     * @param monthStr 月str
     * @return {@link String}
     * @throws ParseException 解析异常
     */
    public static String updateTimeByMonthStr(String endTime, Integer monthStr) throws ParseException {
        // end为空时,赋值为当前时间
        if (StringUtils.isEmpty(endTime)) {
            endTime = DateTimeUtil.getNowTime(TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        }
        // 1、期限月 => 年，月
        int months = monthStr;
        // 年
        int year = months / 12;
        // 月
        int month = 0;
        if (year > 0) {
            month = months % 12; // 6
        } else {
            month = months;
        }
        // 2、执行日期修改
        DateFormat df = new SimpleDateFormat(TimeFormatter.YYYY_MM_DD_HH_MM_SS.getCode());
        Calendar ct = Calendar.getInstance();
        ct.setTime(df.parse(endTime));
        ct.add(Calendar.YEAR, +year);
        ct.add(Calendar.MONTH, +month);

        // 3、返回结果
        return df.format(ct.getTime());
    }

    /***
     * 毫秒转换为可视时长
     * @param ms  毫秒
     * ***/
    public static String getGapTime(long ms) {
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

        StringBuffer sb = new StringBuffer();
        if (day > 0) {
            sb.append(day + "天");
        }
        if (hour > 0) {
            sb.append(hour + "H");
        }
	    if (minute > 0) {
		    sb.append(minute + "分");
	    }
	    if (second > 0) {
		    sb.append(second + "秒");
	    }
//        if (milliSecond > 0) {
//            sb.append(milliSecond + "毫秒");
//        }
	    if (StringUtils.isEmpty(sb.toString())) {
		    sb.append("0秒");
	    }
	    return sb.toString();
    }

    /***
     * 毫秒转换
     * @param ms  毫秒
     * ***/
    public static List<String> getGapTimeList(long ms) {
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;

        List<String> list = new ArrayList<>();
        list.add(day + "");
        list.add(hour + "");
        list.add(minute + "");
        list.add(second + "");

        return list;
    }

    /**
     * 检验时间格式
     *
     * @param time          时间
     * @param timeFormatter 检验时间格式
     * @return
     */
    public static boolean checkDateTime(String time, TimeFormatter timeFormatter) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormatter.getCode(), Locale.CHINA);
        boolean flag = true;
        try {
            LocalDate.parse(time, formatter);
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 判断主方法
     */
    public static boolean validate(String dateString) {
        //使用正则表达式 测试 字符 符合 dddd-dd-dd 的格式(d表示数字)
        Pattern p = Pattern.compile(DATE_REG);
        Matcher m = p.matcher(dateString);
        if (!m.matches()) {
            return false;
        }

        //得到年月日
        String[] array = dateString.split(StringUtils.EN_CENTER_SEPARATOR);
        int year = Integer.parseInt(array[0]);
        int month = Integer.parseInt(array[1]);
        int day = Integer.parseInt(array[2]);

        if (month < 1 || month > 12) {
            return false;
        }
        int[] monthLengths = new int[]{0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (isLeapYear(year)) {
            monthLengths[2] = 29;
        } else {
            monthLengths[2] = 28;
        }
        int monthLength = monthLengths[month];
        return day >= 1 && day <= monthLength;
    }

    /**
     * 是否是闰年
     */
    private static boolean isLeapYear(int year) {
        return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
    }

    /**
     * 获取月份第一天的日期
     ***/
    public static String getFirstDayByMonth(int year, int month) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, 1, 0, 0);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TimeFormatter.YYYY_MM_DD_HH_MM_SS.getCode(), Locale.CHINA);
        return formatter.format(localDateTime);
    }

    /**
     * 获取月份最后一天的日期
     ***/
    public static String getLastDayByMonth(int year, int month) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, 1, 23, 59);
        LocalDateTime lastDay = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TimeFormatter.YYYY_MM_DD_HH_MM_SS.getCode(), Locale.CHINA);
        return formatter.format(lastDay);
    }

    /**
     * 获取月份最后一天的日期
     ***/
    public static String format(Integer year, Integer month, Integer day) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, day, 0, 0, 0);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TimeFormatter.YYYY_MM_DD.getCode(), Locale.CHINA);
        return formatter.format(localDateTime);
    }

    /**
     * 比较2个日期
     *
     * @param dt1           时间字符串
     * @param dt2           时间字符串
     * @param timeFormatter 格式化规则
     * @return
     */
    public static int compareDate(String dt1, String dt2, TimeFormatter timeFormatter) {
        Long long1 = DateTimeToTimestamp(dt1, timeFormatter);
        Long long2 = DateTimeToTimestamp(dt2, timeFormatter);

        return Long.compare(long1, long2);
    }

    /**
     * 将时间字符串转换为其他格式字符串
     *
     * @param time            时间字符串
     * @param timeFormatter   格式化方式
     * @param toTimeFormatter 转换的格式化方式
     * @return 时间字符
     */
    public static String timeFormatConversion(String time, TimeFormatter timeFormatter, TimeFormatter toTimeFormatter) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormatter.getCode(), Locale.CHINA);
        DateTimeFormatter toFormatter = DateTimeFormatter.ofPattern(toTimeFormatter.getCode(), Locale.CHINA);
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
        return localDateTime.format(toFormatter);
    }

    /**
     * 当前是否在时间段内 时间段以 ~ 分割 -1 小于 0 之间 1 大于
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public static Integer getTimeDiffBetween(String beginTime, String endTime) {
        //得到当前时间
        String nowTime = getNowTime(TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        //是否开始
        long timeDiffBegin = getTimeDiff(beginTime, nowTime, TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        if (timeDiffBegin < 0) {
            return -1;
        }
        //是否结束
        long timeDiffEnd = getTimeDiff(nowTime, endTime, TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        return timeDiffEnd >= 0 ? 0 : 1;

    }

    /**
     * 当前是否在时间段内 时间段以 ~ 分割 -1 小于 0 之间 1 大于
     *
     * @param beginTime
     * @return
     */
    public static Integer getTimeDiffNow(String beginTime) {
        //得到当前时间
        String nowTime = getNowTime(TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        //是否开始
        long timeDiffBegin = getTimeDiff(beginTime, nowTime, TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        if (timeDiffBegin < 0) {
            return -1;
        }
        //是否结束
        long timeDiffEnd = getTimeDiff(nowTime, beginTime, TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        return timeDiffEnd >= 0 ? 0 : 1;

    }


    /**
     * 是否超时 时间段以 ~ 分割 -1 小于 0 之间 1 大于
     *
     * @param beginTime
     * @param limitTime
     * @return
     */
    public static Boolean limitTime(String beginTime, String limitTime) {
        //得到当前时间
        String nowTime = getNowTime(TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        //是否开始
        long timeDiffBegin = getTimeDiff(beginTime, nowTime, TimeUnit.MINUTES, TimeFormatter.YYYY_MM_DD_HH_MM_SS);
        if (timeDiffBegin < 0) {
            return true;
        }
        //是否结束
        return timeDiffBegin <= Long.parseLong(limitTime);

    }

    public static void main(String[] args) {
        String nowTimePlus = getNowTimePlus(5, TimeFormatter.YYYY_MM_DD, TimeUnit.MINUTES);
        System.out.println(nowTimePlus);

    }
}
